package modelo.MetodosNumericos;

import modelo.abstraccionesGeometricas.Intervalo;
import modelo.excepciones.NoExisteLaIntegral;
import modelo.excepciones.ValorNoPertenecienteAlDominio;
import modelo.funciones.Funcion;

public class Simpson implements Integrar {
	
	/**
	 * Esta variable se usa en el metodo calcularIntegral. Su valor por defecto es 10.
	 */
	public static int cantidadDeDivisiones = 10;
	
	public double aplicar(Funcion funcion, Intervalo intervalo) {
		return calcularIntegral(funcion,intervalo,cantidadDeDivisiones);
	}
	
	/**
	 * Este metodo calcula la integral de la funcion pasada como parametro en el intervalo dado.
	 * Es una implementacion del <a href="http://es.wikipedia.org/wiki/Regla_de_Simpson">Metodo de Simpson </A HREF>
	 * @param divisiones Un int indicando en cuantas divisiones se quiere dividir el intervalo original 
	 * 					 para aplicar el metodo de simpson. 
	 * @return Un double que contiene el resultado de calcular la integral.
	 */
	public double calcularIntegral(Funcion funcion, Intervalo intervalo, int divisiones){
        double resultado = 0;
		try {
			double a = intervalo.getComienzo();
	        double b = intervalo.getFinal();
			if(divisiones%2==1) divisiones++;     
	        double h=(b-a)/divisiones;
	        
	        double suma=funcion.evaluar(a)+funcion.evaluar(b);
	        
	        for(int i=1; i<divisiones; i+=2){
	        	suma+=4*funcion.evaluar(a+i*h);
	        }
	        for(int i=2; i<divisiones; i+=2){
	            suma+=2*funcion.evaluar(a+i*h);
	        }
	        resultado = (suma*h/3);
	        
		}
		catch (ValorNoPertenecienteAlDominio e) {
			throw new NoExisteLaIntegral();
		}
        return resultado;
 }

}
